package org.ala.tiktools.sharddb.tx;

import java.util.concurrent.Callable;

import org.ala.tiktools.sharddb.db.ThreadLocalLookupKey;

/**
 * 事务任务
 *
 * @author ala
 * @date 2024-12-27 15:28
 */
public class TransactionTask {


    /**
     *  任务状态
     */
    protected Status status = Status.UnBegin;
    /**
     *  数据源key
     */
    protected String shardKey;
    /**
     *  任务体
     */
    protected Callable<?> call;
    /**
     *  任务返回值
     */
    protected Object res;
    /**
     *  过程中抛出的异常
     */
    protected Exception e;
    /**
     *  已经完整提交的事务，只能走补偿
     */
    protected IShardTransaction.ICompensation compensation;
    /**
     *  任务的事务状态
     */
    protected ShardTransactionStatus ts;
    /**
     *  任务名称（打日志用）
     *  <p> 自行保证唯一性
     */
    protected String name;
    /**
     *  额外信息
     *  <p> 补偿时会回传这些信息
     */
    protected Object metadata;


    public static <T> TransactionTask build(String name, String shardKey, ShardTransactionStatus ts, Callable<T> run) {
        TransactionTask task = new TransactionTask();
        task.name = name;
        task.status = Status.UnBegin;
        task.shardKey = shardKey;
        task.call = run;
        task.ts = ts;
        return task;
    }


    /**
     *  还行任务体
     */
    public void doTask() {
        try {
            status = Status.Running;
            ThreadLocalLookupKey.setLookup(shardKey);

            this.res = this.call.call();

            status = Status.Success;
        } catch (Exception e) {
            this.e = e;
            this.status = Status.Error;
        } finally {
            ThreadLocalLookupKey.clear();
        }
    }


    /**
     *  任务状态
     */
    public static enum Status {
        UnBegin,
        Running,
        Success,
        Error
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    public String getShardKey() {
        return shardKey;
    }

    public void setShardKey(String shardKey) {
        this.shardKey = shardKey;
    }

    public Callable<?> getCall() {
        return call;
    }

    public void setCall(Callable<?> call) {
        this.call = call;
    }

    public Object getRes() {
        return res;
    }

    public void setRes(Object res) {
        this.res = res;
    }

    public Exception getE() {
        return e;
    }

    public void setE(Exception e) {
        this.e = e;
    }

    public IShardTransaction.ICompensation getCompensation() {
        return compensation;
    }

    public void setCompensation(IShardTransaction.ICompensation compensation) {
        this.compensation = compensation;
    }

    public ShardTransactionStatus getTs() {
        return ts;
    }

    public void setTs(ShardTransactionStatus ts) {
        this.ts = ts;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Object getMetadata() {
        return metadata;
    }

    public void setMetadata(Object metadata) {
        this.metadata = metadata;
    }

    public TransactionTask metadata(Object metadata) {
        this.metadata = metadata;
        return this;
    }
}
